package com.systop.asset.service.impl;

import com.google.zxing.WriterException;
import com.systop.asset.entity.Asset;
import com.systop.asset.entity.RestResponse;
import com.systop.asset.entity.vo.AssetVo;
import com.systop.asset.enums.AssetStatus;
import com.systop.asset.enums.HttpCodeEnum;
import com.systop.asset.exception.SystemException;
import com.systop.asset.mapper.AssetMapper;
import com.systop.asset.service.IAssetService;
import com.systop.asset.utils.QRCodeGenerator;
import com.systop.asset.utils.RandomCodeGenerator;
import lombok.experimental.Accessors;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>ClassName : AssetServiceImpl</p>
 * <p>Description : </p>
 *
 * @author 孙伟光
 * @version 1.0
 * @date 2025/6/26 10:31
 */
@Service
public class AssetServiceImpl  implements IAssetService {

    @Autowired
    private AssetMapper assetMapper;

    @Autowired
    private QRCodeGenerator qrCodeGenerator;

    /**
     * 根据资产ID获取资产详情
     *
     * @param id 资产ID，不能为null
     * @return 查询到的资产对象
     * @throws SystemException 当参数为空或资产不存在时抛出异常
     */
    @Override
    public Asset getAssetById(Long id) {
        // 参数校验：检查资产ID是否为空
        if (id == null) {
            throw new SystemException(HttpCodeEnum.PARAM_NOT_NULL);
        }
        // 调用Mapper层查询资产信息
        Asset asset = assetMapper.selectAssetById(id);
        // 检查查询结果是否为空
        if (asset == null) {
            throw new SystemException(HttpCodeEnum.ASSET_NOT_EXIST);
        }
        return asset;
    }
    
    @Override
    public AssetVo getAssetVoById(Long id) {
        // 参数校验：检查资产ID是否为空
        if (id == null) {
            throw new SystemException(HttpCodeEnum.PARAM_NOT_NULL);
        }
        // 调用Mapper层查询资产信息
        AssetVo assetVo = assetMapper.selectAssetVoById(id);
        // 检查查询结果是否为空
        if (assetVo == null) {
            throw new SystemException(HttpCodeEnum.ASSET_NOT_EXIST);
        }
        return assetVo;
    }

    /**
     * 根据条件查询资产列表
     *
     * @param asset 资产查询条件对象，可以为null表示查询所有资产
     * @return 符合条件的资产列表，不会返回null，若无数据则返回空列表
     */
    @Override
    public List<AssetVo> getAssetList(Asset asset) {
        // 调用Mapper层查询符合条件的资产列表
        List<AssetVo> assetList = assetMapper.selectAssetJoinList(asset);
        return assetList;
    }

    /**
     * 新增单个资产信息
     * <p>该方法会向数据库插入一条新的资产记录</p>
     *
     * @param asset 资产实体对象，包含需要新增的资产信息，不能为null
     * @return 受影响的行数，通常1表示成功插入，0表示插入失败
     * @throws SystemException 如果参数校验失败或数据库操作异常
     */
    @Override
    @Transactional
    public int addAsset(Asset asset) {
        // 参数校验
        if (asset == null) {
            throw new SystemException(HttpCodeEnum.PARAM_NOT_NULL);
        }
        //系统生成资产编码（格式：ASSET-年月日-6位随机数）
        String assetCode = RandomCodeGenerator.generateAssetCode();
        asset.setAssetCode(assetCode);
        //系统生成二维码图片，二维码中存储资产编码
        try{
            String qrcode = qrCodeGenerator.generateQRCode(assetCode, 300, 300);
            asset.setQrcode(qrcode);
        } catch (Exception e) {
            throw new SystemException(500, "二维码生成失败");
        }
        //系统默认添加状态为闲置
        asset.setStatus(AssetStatus.IDLE.getCode());
        System.out.println("============" + SecurityContextHolder.getContext().getAuthentication().getCredentials());
        //负责人ID
        asset.setPrincipal((Long)SecurityContextHolder.getContext().getAuthentication().getCredentials());
        //系统生成批次号
        String batchNumber = RandomCodeGenerator.generateBatchNumber();
        asset.setBatchNumber(batchNumber);
        // 调用Mapper层方法执行资产插入操作
        int result = assetMapper.insertAsset(asset);
        // 返回数据库操作结果
        return result;
    }

    @Override
    @Transactional
    public int addAssetBatch(List<Asset> assets) {
        // 参数校验：检查资产列表是否为空
        if (assets == null || assets.isEmpty()) {
            throw new SystemException(HttpCodeEnum.PARAM_NOT_NULL);
        }
        //系统生成批次号
        String batchNumber = RandomCodeGenerator.generateBatchNumber();

        // 循环资产列表，对每个资产进行业务逻辑处理
        for (Asset asset : assets) {
            //系统生成资产编码（格式：ASSET-年月日-6位随机数）
            String assetCode = RandomCodeGenerator.generateAssetCode();
            asset.setAssetCode(assetCode);
            //系统生成二维码图片，二维码中存储资产编码
            try{
                String qrcode = qrCodeGenerator.generateQRCode(assetCode, 300, 300);
                asset.setQrcode(qrcode);
            } catch (Exception e) {
                throw new SystemException(500, "二维码生成失败");
            }
            //系统默认添加状态为闲置
            asset.setStatus(AssetStatus.IDLE.getCode());
            //负责人ID
            asset.setPrincipal((Long)SecurityContextHolder.getContext().getAuthentication().getCredentials());
            //填充批次号
            asset.setBatchNumber(batchNumber);
        }
        int result = assetMapper.insertAssetBatch(assets);
        return result;
    }

    /**
     * 复制资产时，不用生成新的批次号,但是需要把序列号置空
     * @param asset 资产信息
     * @param count 批量添加个数
     * @return 操作结果响应
     */
    @Override
    @Transactional
    public int copy(Asset asset, int count) {
        // 参数校验：检查资产列表是否为空
        if (asset == null) {
            throw new SystemException(HttpCodeEnum.PARAM_NOT_NULL);
        }

        List<Asset> assets = new ArrayList<>();
        // 循环资产列表，对每个资产进行业务逻辑处理
        for (int i = 0; i < count; i++) {
            // 克隆资产对象，避免影响原始对象
            Asset newAsset = new Asset();
            BeanUtils.copyProperties(asset, newAsset);
            //修改序列号为空
            newAsset.setSerialNumber(null);
            //系统生成资产编码
            String assetCode = RandomCodeGenerator.generateAssetCode();
            newAsset.setAssetCode(assetCode);
            //系统生成二维码图片，二维码中存储资产编码
            try{
                String qrcode = qrCodeGenerator.generateQRCode(assetCode, 300, 300);
                newAsset.setQrcode(qrcode);
            } catch (Exception e) {
                throw new SystemException(500, "二维码生成失败");
            }
            //系统默认添加状态为闲置
            newAsset.setStatus(AssetStatus.IDLE.getCode());
            //负责人ID
            newAsset.setPrincipal((Long)SecurityContextHolder.getContext().getAuthentication().getCredentials());
            //处理好的对象填充到集合中
            assets.add(newAsset);
        }
        int result = assetMapper.insertAssetBatch(assets);
        return result;
    }

    /**
     * 批量新增资产
     * @param asset 资产信息
     * @param count 批量添加个数
     * @return 操作结果响应
     */
    @Override
    @Transactional
    public int addAssetBatch(Asset asset, int count) {
        // 参数校验：检查资产列表是否为空
        if (asset == null) {
            throw new SystemException(HttpCodeEnum.PARAM_NOT_NULL);
        }
        //系统生成批次号
        String batchNumber = RandomCodeGenerator.generateBatchNumber();
        List<Asset> assets = new ArrayList<>();
        // 循环资产列表，对每个资产进行业务逻辑处理
        for (int i = 0; i < count; i++) {
            // 克隆资产对象，避免影响原始对象
            Asset newAsset = new Asset();
            BeanUtils.copyProperties(asset, newAsset);

            //系统生成资产编码
            String assetCode = RandomCodeGenerator.generateAssetCode();
            newAsset.setAssetCode(assetCode);
            //系统生成二维码图片，二维码中存储资产编码
            try{
                String qrcode = qrCodeGenerator.generateQRCode(assetCode, 300, 300);
                newAsset.setQrcode(qrcode);
            } catch (Exception e) {
                throw new SystemException(500, "二维码生成失败");
            }
            //系统默认添加状态为闲置
            newAsset.setStatus(AssetStatus.IDLE.getCode());
            //负责人ID
            newAsset.setPrincipal((Long)SecurityContextHolder.getContext().getAuthentication().getCredentials());
            //填充批次号
            newAsset.setBatchNumber(batchNumber);
            //处理好的对象填充到集合中
            assets.add(newAsset);
        }
        int result = assetMapper.insertAssetBatch(assets);
        return result;
    }

    /**
     * 更新单个资产信息
     * <p>该方法会根据资产ID更新数据库中对应的资产记录</p>
     *
     * @param asset 资产实体对象，包含需要更新的资产信息，不能为null
     * @return 受影响的行数，1表示成功更新，0表示更新失败
     * @throws SystemException 如果参数校验失败或数据库操作异常
     */
    @Override
    @Transactional
    public int updateAsset(Asset asset) {
        // 调用Mapper层方法执行资产更新操作
        int result = assetMapper.updateAsset(asset);
        // 返回数据库操作结果
        return result;
    }

    /**
     * 根据资产ID删除资产信息
     * <p>该方法会从数据库中删除指定ID的资产记录</p>
     *
     * @param id 要删除的资产ID，不能为null
     * @return 受影响的行数，1表示成功删除，0表示删除失败
     * @throws SystemException 如果参数为空或数据库操作异常
     */
    @Override
    @Transactional
    public int deleteAsset(Long id) {
        // 调用Mapper层方法执行资产删除操作
        int result = assetMapper.deleteAsset(id);
        // 返回数据库操作结果
        return result;
    }
    @Override
    public List<Map<String, Object>> getAssetStatusStatistics() {
        // 从数据库获取分组统计结果
        List<Map<String, Object>> rawStats = assetMapper.countByStatusGroup();

        // 转换为前端需要的格式
        List<Map<String, Object>> result = new ArrayList<>();

        for (Map<String, Object> stat : rawStats) {
            Integer statusCode = (Integer) stat.get("status");
            String statusName = AssetStatus.getNameByCode(statusCode);

            Map<String, Object> statInfo = new HashMap<>();
            statInfo.put("status", statusName);
            statInfo.put("count", stat.get("count"));
            statInfo.put("percentage", stat.get("percentage"));

            result.add(statInfo);
        }
        return result;
    }

    @Override
    public List<Map<String, Object>> getAssetCategoryStatistics() {
        List<Map<String, Object>> rawData = assetMapper.countByCategoryAndStatusGroup();

        return rawData.stream().map(item -> {
            Map<String, Object> result = new HashMap<>();
            result.put("categoryName", item.get("categoryName"));
            result.put("total", item.get("total"));

            List<Map<String, Object>> statusDetails = new ArrayList<>();
            statusDetails.add(createStatusDetail("闲置", ((Number)item.get("idleCount")).longValue()));
            statusDetails.add(createStatusDetail("使用中", ((Number)item.get("inUseCount")).longValue()));
            statusDetails.add(createStatusDetail("维修中", ((Number)item.get("repairingCount")).longValue()));
            statusDetails.add(createStatusDetail("已报废", ((Number)item.get("scrappedCount")).longValue()));
            statusDetails.add(createStatusDetail("其他", ((Number)item.get("otherCount")).longValue()));

            result.put("statusDetails", statusDetails);
            return result;
        }).collect(Collectors.toList());
    }

    @Override
    public List<Map<String, Object>> getAssetDeptStatistics() {
        List<Map<String, Object>> rawData = assetMapper.countByDeptAndStatusGroup();

        return rawData.stream().map(item -> {
            Map<String, Object> result = new HashMap<>();
            result.put("deptName", item.get("deptName"));
            result.put("total", item.get("total"));
            result.put("percentage", item.get("percentage"));

            List<Map<String, Object>> statusDetails = new ArrayList<>();
            statusDetails.add(createStatusDetail("闲置", ((Number)item.get("idleCount")).longValue()));
            statusDetails.add(createStatusDetail("领用中", ((Number)item.get("receiveCount")).longValue()));
            statusDetails.add(createStatusDetail("使用中", ((Number)item.get("inUseCount")).longValue()));
            statusDetails.add(createStatusDetail("维修中", ((Number)item.get("repairingCount")).longValue()));
            statusDetails.add(createStatusDetail("已报废", ((Number)item.get("scrappedCount")).longValue()));
            statusDetails.add(createStatusDetail("其他", ((Number)item.get("otherCount")).longValue()));

            result.put("statusDetails", statusDetails);

            return result;
        }).collect(Collectors.toList());
    }


    private Map<String, Object> createStatusDetail(String status, Long count) {
        Map<String, Object> detail = new HashMap<>();
        detail.put("status", status);
        detail.put("count", count);
        return detail;
    }

    @Override
    public List<Map<String, Object>> getAssetLocationStatistics() {
        // 获取所有资产总数用于计算占比
        Long totalCount = assetMapper.selectTotalAssetCount();

        List<Map<String, Object>> rawData = assetMapper.countByLocationGroup();

        return rawData.stream().map(item -> {
            Map<String, Object> result = new HashMap<>();
            result.put("locationName", item.get("locationName"));
            Long count = ((Number) item.get("count")).longValue();
            result.put("count", count);

            // 计算百分比并保留两位小数
            double percentage = (count.doubleValue() / totalCount.doubleValue()) * 100;
            result.put("percentage", Math.round(percentage * 100.0) / 100.0);

            return result;
        }).collect(Collectors.toList());
    }

}
